package com.corpgovernment.organization.util;


import com.alibaba.excel.EasyExcel;
import com.corpgovernment.api.ordercenter.dto.annotation.ExcelColumn;
import com.corpgovernment.api.platform.enums.reconciliation.ExcelPostEnum;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.utils.DateUtil;
import com.corpgovernment.organization.dto.ExcelValidationInfoDTO;
import com.corpgovernment.organization.enumm.FileTemplateEnum;
import com.corpgovernment.organization.metric.MetricService;
import com.corpgovernment.organization.vo.*;
import com.corpgovernment.permission.vo.DownloadRoleDataPermissionExcelVo;
import com.corpgovernment.permission.vo.DownloadRolePermissionExcelVo;
import com.corpgovernment.permission.vo.DownloadRolePermissionTemplateVo;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.corpgovernment.organization.metric.MetricService.ORGANIZATION_MANAGE_DOWNLOAD_EMPLOYEE;
import static com.corpgovernment.organization.metric.MetricService.SYNC;

/**
 * @Description: Excel构建工具类
 * @Author cwangk
 * @Date 2019/6/13
 */

@Component
public class ExcelUtils {

    private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);

    private final static String EXCEL2003 = "xls";
    private final static String EXCEL2007 = "xlsx";
    private final static String LineNo = "lineNo";

    /**
     * 动态报表下载
     */
    public void downloadDynamicExcel(HttpServletResponse response, DynamicExcelCreateVO vo) {
        try {
            //构建excel
            Workbook workbook = buildExcel(vo.getDataList(), vo.getHeaders());
            String filename = URLEncoder.encode(vo.getFileName() + "." + vo.getPostfix(), "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("报表下载失败", e);
        }
    }

    /**
     * Excel构建
     */
    private Workbook buildExcel(List<Map<String, String>> dataList, List<String> headers) {
        Workbook wb = new XSSFWorkbook();
        AtomicInteger ai = new AtomicInteger();
        Sheet sheet = buildDynamicHeader(headers, wb, ai.getAndIncrement());
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataList.forEach(data -> {
                Row row1 = sheet.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                headers.forEach(header -> {
                    String value = data.get(header);
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value);
                    }
                });
            });
        }
        wb.getSheet("Sheet1").createFreezePane(0, 1, 0, 1);
        return wb;
    }

    /**
     * 构建excel表头
     */
    private Sheet buildDynamicHeader(List<String> headers, Workbook wb, int index) {
        Sheet sheet = wb.createSheet("Sheet1");
        Row row = sheet.createRow(index);
        AtomicInteger aj = new AtomicInteger();
        //写入头部
        headers.forEach(columnName -> {
            Cell cell = row.createCell(aj.getAndIncrement());
            CellStyle cellStyle = wb.createCellStyle();
            Font font = wb.createFont();
            font.setBold(Boolean.TRUE);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            cell.setCellValue(columnName);
        });
        return sheet;
    }

    /**
     * 报表下载
     *
     * @param response
     * @param vo
     */
    public void downloadExcelDocument(HttpServletResponse response, ExcelCreateVO vo) {
        try {
            //获取需要下载数据filed
            List<Field> fieldList = getColumn(vo.getDynamicObject(), vo.getCls(), vo.isDynamic());
            //构建excel
            Workbook workbook = buildExcel(vo.getDataList(), fieldList, null);
            if(StringUtils.isNotBlank(vo.getSheetName())) {
                workbook.setSheetName(0,vo.getSheetName());
            }
            String filename = URLEncoder.encode(vo.getFileName() + "." + vo.getPostfix(), "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("报表下载失败", e);
        }
    }

    /**
     * 报表下载easyExcel
     *
     * @param response
     * @param vo
     */
    public void downloadEasyExcelDocument(HttpServletResponse response, ExcelCreateVO vo) {
        try {

            List<Field> fieldList = getColumn(vo.getDynamicObject(), vo.getCls(), vo.isDynamic());
            //构建excel
            OutputStream out = response.getOutputStream();
            EasyExcel.write(out, vo.getCls()).sheet(vo.getSheetName()).doWrite(vo.getDataList());

            String filename = URLEncoder.encode(vo.getFileName() + "." + vo.getPostfix(), "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
        } catch (IOException e) {
            log.error("报表下载失败", e);
        }
    }

    /**
     * 报表下载
     *
     * @param response
     * @param vo
     */
    public void downloadExcelValidationDocument(HttpServletResponse response, ExcelCreateVO vo, List<ExcelValidationInfoDTO> validationInfoVos) {
        try {
            //获取需要下载数据filed
            List<Field> fieldList = getColumn(vo.getDynamicObject(), vo.getCls(), vo.isDynamic());
            //构建excel
            Workbook workbook = buildExcel(vo.getDataList(), fieldList, validationInfoVos);
            String filename = URLEncoder.encode(vo.getFileName() + "." + vo.getPostfix(), "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("报表下载失败", e);
        }
    }

    /**
     * Excel构建
     *
     * @param dataList
     * @param fieldList
     * @param <T>
     */
    private <T> Workbook buildExcel(List<T> dataList, List<Field> fieldList, List<ExcelValidationInfoDTO> validationInfoVos) {
        Workbook wb = new XSSFWorkbook();
        AtomicInteger ai = new AtomicInteger();
        Sheet sheet = buildHeader(fieldList, wb, ai.getAndIncrement());
        if (CollectionUtils.isNotEmpty(dataList)) {
            dataList.forEach(t -> {
                Row row1 = sheet.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());

                    }
                });
            });

            if (CollectionUtils.isNotEmpty(validationInfoVos)) {
                validationInfoVos.forEach(info -> {
                    setHSSFValidation(sheet, info.getValidationList(), 1, dataList.size(), info.getFirstCol(), info.getEndCol());
                });
            }
        }
        wb.getSheet("Sheet1").createFreezePane(0, 1, 0, 1);
        return wb;
    }

    /**
     * 获取报表注解
     *
     * @param cls 模板类
     * @param <T>
     * @return
     */
    private <T> List<Field> getColumn(Class<T> cls) {
        Field[] fields = cls.getDeclaredFields();
        return Arrays.stream(fields)
                .filter(field -> filterField(null, false, field))
                .sorted(Comparator.comparing(field -> {
                    int col = 0;
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null) {
                        col = annotation.col();
                    }
                    return col;
                })).collect(Collectors.toList());
    }

    /**
     * 获取报表注解
     *
     * @param object    数据源类
     * @param cls       原报表模板
     * @param isDynamic 是否动态判断报表字段
     * @param <T>
     * @return
     */
    public <T> List<Field> getColumn(Object object, Class<T> cls, boolean isDynamic) {
        if (null == object) {
            return getColumn(cls);
        }
        Field[] fields = object.getClass().getDeclaredFields();
        List<Field> fieldList = Arrays.stream(fields)
                .filter(field -> filterField(object, isDynamic, field))
                .sorted(Comparator.comparing(field -> {
                    int col = 0;
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null) {
                        col = annotation.col();
                    }
                    return col;
                })).collect(Collectors.toList());
        List<Field> resultList = new ArrayList<>();
        fieldList.stream().forEach(p -> {
            try {
                Field field = cls.getDeclaredField(p.getName());
                field.setAccessible(true);
                resultList.add(field);
            } catch (NoSuchFieldException e) {
                log.error("报表生成异常", e);
            }
        });
        return resultList;
    }

    /**
     * 过滤是否含有报表注解属性
     *
     * @param object
     * @param isDynamic
     * @param field
     * @return
     */
    private boolean filterField(Object object, boolean isDynamic, Field field) {
        ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
        if (annotation == null || annotation.col() < 1) {
            return false;
        }
        field.setAccessible(true);
        if (isDynamic) {
            try {
                return field.getBoolean(object);
            } catch (IllegalAccessException e) {
                log.error("获取报表注解异常", e);
                return false;
            }
        }
        return true;
    }


    /**
     * 构建excel表头
     *
     * @param fieldList
     * @param wb
     * @param index
     * @return
     */
    private Sheet buildHeader(List<Field> fieldList, Workbook wb, int index) {
        Sheet sheet = wb.createSheet("Sheet1");
        Row row = sheet.createRow(index);
        AtomicInteger aj = new AtomicInteger();
        //写入头部
        fieldList.forEach(field -> {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            String columnName = "";
            if (annotation != null) {
                columnName = annotation.value();
            }

            Cell cell = row.createCell(aj.getAndIncrement());
            CellStyle cellStyle = wb.createCellStyle();
            Font font = wb.createFont();
            font.setBold(Boolean.TRUE);
            if (annotation != null) {
                if (annotation.headerColor().equals("red")) {
                    font.setColor(IndexedColors.RED.getIndex());
                }
            }
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            cell.setCellValue(columnName);
        });
        return sheet;
    }

    /**
     * 将excel文件转为bean
     *
     * @param sheet
     * @param clz
     * @param <T>
     * @return
     */
    public <T> List<T> getBeanListFromExcel(Sheet sheet, Class<T> clz) {
        List<T> list = new ArrayList<>();
        List<Field> fieldList = getColumn(clz);
        int rows = sheet.getPhysicalNumberOfRows();
        try {
            for (int i = 1; i < rows; i++) {
                Row row = sheet.getRow(i);
                T t = getBeanFromRow(clz, fieldList, row);
                if (t != null) {
                    list.add(t);
                }
            }
        } catch (Exception e) {
            log.error("报表读取失败", e);
        }
        return list;
    }
    /**
     * 从第二行开始读取数据，
     * @param sheet
     * @param clz
     * @return
     * @param <T>
     */
    public <T> List<T> getBeanListFromExcelTwo(Sheet sheet, Class<T> clz) {
        List<T> list = new ArrayList<>();
        List<Field> fieldList = getColumn(clz);
        int rows = sheet.getPhysicalNumberOfRows();
        try {
            for (int i = 2; i < rows; i++) {
                Row row = sheet.getRow(i);
                T t = getBeanFromRow(clz, fieldList, row);
                if (t != null) {
                    list.add(t);
                }
            }
        } catch (Exception e) {
            log.error("报表读取失败", e);
        }
        return list;
    }

    /**
     * 将每一行数据转为对应的bean
     *
     * @param clz       目标bean
     * @param fieldList bean filed集合
     * @param row       报表每一行
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private <T> T getBeanFromRow(Class<T> clz, List<Field> fieldList, Row row) throws InstantiationException, IllegalAccessException {
        T t = clz.newInstance();
        if (row == null) {
            return t;
        }
        int size = fieldList.size();
        if (row.cellIterator().hasNext()) {
            row.cellIterator().forEachRemaining(cell -> {
                int columnIndex = cell.getColumnIndex();
                if (columnIndex >= size) {
                    return;
                }
				int cellType = cell.getCellType();
                String value;
                if (cellType == Cell.CELL_TYPE_NUMERIC && HSSFDateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    value = DateUtil.dateToYMD(date);
                } else {
                    cell.setCellType(Cell.CELL_TYPE_STRING);
                    value = cell.getStringCellValue();
                }
                Field field = fieldList.get(columnIndex);
                setValue(field, t, value);
            });
        }
        //赋值行号
        Field lineNo = Optional.of(Arrays.stream(clz.getDeclaredFields()).filter(x -> LineNo.equals(x.getName())).findFirst()).get().orElse(null);
        if (lineNo != null) {
            lineNo.setAccessible(true);
            setValue(lineNo, t, String.valueOf(row.getRowNum() + 1));
        }
        return t;
    }

    /**
     * 校验报表头
     *
     * @param sheet
     * @param clz
     * @param <T>
     * @return
     */
    public <T> boolean checkoutHead(Sheet sheet, Class<T> clz) {
        try {
            List<Field> fieldList = getColumn(clz);
            Row row = sheet.getRow(0);
            int cellNumber = row.getPhysicalNumberOfCells();
            for (int j = 0; j < cellNumber; j++) {
                Cell cell = row.getCell(j);
                if (cell == null) {
                    continue;
                }
                cell.setCellType(Cell.CELL_TYPE_STRING);
                String value = cell.getStringCellValue();
                ExcelColumn annotation = fieldList.get(j).getAnnotation(ExcelColumn.class);
                String columnName = "";
                if (annotation != null) {
                    columnName = annotation.value();
                }
                if (!columnName.equalsIgnoreCase(value)) {
                    return false;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public <T> List<T> readExcel(Class<T> cls, MultipartFile file) throws Exception {
        String fileName = file.getOriginalFilename();
        if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
            log.error("上传文件格式不正确");
        }

        List<T> dataList = new ArrayList<>();
        Workbook workbook = null;
        try {
            InputStream is = file.getInputStream();
            if (fileName.endsWith(EXCEL2007)) {
//                FileInputStream is = new FileInputStream(new File(path));
                workbook = new XSSFWorkbook(is);
            }
            if (fileName.endsWith(EXCEL2003)) {
//                FileInputStream is = new FileInputStream(new File(path));
                workbook = new HSSFWorkbook(is);
            }
            if (workbook != null) {


                //类映射  注解 value-->bean columns
                Map<String, List<Field>> classMap = new HashMap<>();
                List<Field> fields = Stream.of(cls.getDeclaredFields()).collect(Collectors.toList());
                fields.forEach(
                        field -> {
                            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                            if (annotation != null) {
                                String value = annotation.value();
                                if (StringUtils.isBlank(value)) {
                                    return;//return起到的作用和continue是相同的 语法
                                }
                                if (!classMap.containsKey(value)) {
                                    classMap.put(value, new ArrayList<>());
                                }
                                field.setAccessible(true);
                                classMap.get(value).add(field);
                            }
                        }
                );
                //索引-->columns
                Map<Integer, List<Field>> reflectionMap = new HashMap<>(16);
                //默认读取第一个sheet
                Sheet sheet = workbook.getSheetAt(0);
                if (!checkoutHead(sheet, cls)) {
                    throw new Exception("导入表格和导出模板不一致");
                }
                boolean firstRow = true;
                for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
                    Row row = sheet.getRow(i);
                    //首行  提取注解
                    if (firstRow) {
                        for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                            Cell cell = row.getCell(j);
                            String cellValue = getCellValue(cell);
                            if (classMap.containsKey(cellValue)) {
                                reflectionMap.put(j, classMap.get(cellValue));
                            }
                        }
                        firstRow = false;
                    } else {
                        //忽略空白行
                        if (row == null) {
                            continue;
                        }
                        try {
                            T t = cls.newInstance();
                            //判断是否为空白行
                            boolean allBlank = true;
                            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
                                if (reflectionMap.containsKey(j)) {
                                    Cell cell = row.getCell(j);
                                    String cellValue = getCellValue(cell);
                                    if (StringUtils.isNotBlank(cellValue)) {
                                        allBlank = false;
                                    }
                                    List<Field> fieldList = reflectionMap.get(j);
                                    fieldList.forEach(
                                            x -> {
                                                try {
                                                    handleField(t, cellValue, x);
                                                } catch (Exception e) {
                                                    log.error(String.format("reflect field:%s value:%s exception!", x.getName(), cellValue), e);
                                                }
                                            }
                                    );
                                }
                            }
                            if (!allBlank) {
                                dataList.add(t);
                            } else {
                                log.warn(String.format("row:%s is blank ignore!", i));
                            }
                        } catch (Exception e) {
                            log.error(String.format("parse row:%s exception!", i), e);
                        }
                    }
                }
            }
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception e) {
                    log.error(String.format("parse excel exception!"), e);
                }
            }
        }
        return dataList;
    }

    private String getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
            } else {
                return BigDecimal.valueOf(cell.getNumericCellValue()).toString();
            }
        } else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
            return trimToEmpty(cell.getStringCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
            return trimToEmpty(cell.getCellFormula());
        } else if (cell.getCellType() == Cell.CELL_TYPE_BLANK) {
            return "";
        } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
            return "ERROR";
        } else {
            return cell.toString().trim();
        }

    }

    public static String trimToEmpty(String str) {
        return str == null ? "" : str.trim();
    }

    private <T> void handleField(T t, String value, Field field) throws Exception {
        Class<?> type = field.getType();
        if (type == null || type == void.class || StringUtils.isBlank(value)) {
            return;
        }
        if (type == Object.class) {
            field.set(t, value);
            //数字类型
        } else if (type.getSuperclass() == null || type.getSuperclass() == Number.class) {
            if (type == int.class || type == Integer.class) {
                field.set(t, NumberUtils.toInt(value));
            } else if (type == long.class || type == Long.class) {
                field.set(t, NumberUtils.toLong(value));
            } else if (type == byte.class || type == Byte.class) {
                field.set(t, NumberUtils.toByte(value));
            } else if (type == short.class || type == Short.class) {
                field.set(t, NumberUtils.toShort(value));
            } else if (type == double.class || type == Double.class) {
                field.set(t, NumberUtils.toDouble(value));
            } else if (type == float.class || type == Float.class) {
                field.set(t, NumberUtils.toFloat(value));
            } else if (type == char.class || type == Character.class) {
                field.set(t, CharUtils.toChar(value));
            } else if (type == boolean.class) {
                field.set(t, BooleanUtils.toBoolean(value));
            } else if (type == BigDecimal.class) {
                field.set(t, new BigDecimal(value));
            }
        } else if (type == Boolean.class) {
            field.set(t, BooleanUtils.toBoolean(value));
        } else if (type == Date.class) {
            //
            field.set(t, value);
        } else if (type == String.class) {
            field.set(t, value);
        } else {
            Constructor<?> constructor = type.getConstructor(String.class);
            field.set(t, constructor.newInstance(value));
        }
    }


    /**
     * 根据类型设置value
     *
     * @param field
     * @param entity
     * @param value
     * @param <T>
     */
    public <T> void setValue(Field field, T entity, String value) {
        if (StringUtils.isBlank(value)) {
            return;
        }
        Class<?> fieldType = field.getType();
        try {
            if (String.class == fieldType) {
                field.set(entity, String.valueOf(value));
            } else if ((Integer.TYPE == fieldType)
                    || (Integer.class == fieldType)) {
                field.set(entity, Integer.valueOf(value));
            } else if ((Long.TYPE == fieldType)
                    || (Long.class == fieldType)) {
                field.set(entity, Long.valueOf(value));
            } else if (BigDecimal.class == fieldType) {
                field.set(entity, new BigDecimal(value));
            } else if ((Float.TYPE == fieldType)
                    || (Float.class == fieldType)) {
                field.set(entity, Float.valueOf(value));
            } else if ((Short.TYPE == fieldType)
                    || (Short.class == fieldType)) {
                field.set(entity, Short.valueOf(value));
            } else if ((Double.TYPE == fieldType)
                    || (Double.class == fieldType)) {
                field.set(entity, Double.valueOf(value));
            }
        } catch (Exception e) {
            log.error("excel赋值错误", e);
        }
    }

    /**
     * 设置某些列的值只能输入预制的数据,显示下拉框.
     *
     * @param sheet    要设置的sheet.
     * @param textlist 下拉框显示的内容
     * @param firstRow 开始行
     * @param endRow   结束行
     * @param firstCol 开始列
     * @param endCol   结束列
     */
    public Sheet setHSSFValidation(Sheet sheet,
                                   String[] textlist, int firstRow, int endRow, int firstCol,
                                   int endCol) {
        XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet) sheet);
        XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper
                .createExplicitListConstraint(textlist);
        CellRangeAddressList addressList = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, addressList);
        sheet.addValidationData(validation);
        return sheet;
    }

    public JSONResult<String> downloadTemplate(String templateName, HttpServletResponse response) {
        OutputStream out = null;
        try {
            String dealName = FileTemplateEnum.getTemplateName(templateName);
            if (StringUtils.isEmpty(dealName)) {
                return JSONResult.errorMsg("未找到模板");
            }
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(dealName.getBytes("gb2312"), "ISO8859-1"));
            out = new BufferedOutputStream(response.getOutputStream());
            InputStream inputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(String.format("syncorgexceltemplate/%s", dealName));
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = inputStream.read(buff, 0, 100)) > 0) {
                out.write(buff, 0, rc);
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            log.error("下载模板异常", e);
            return JSONResult.errorMsg("下载模板异常");
        }
        return JSONResult.success(null);
    }

    public void downloadExcelRolePermission(HttpServletResponse response, DownloadRolePermissionTemplateVo vo){
        try {
            //构建excel
            Workbook workbook = buildExcel(vo);
            String filename = URLEncoder.encode(vo.getFileName() + "." + ExcelPostEnum.xlsx, "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("角色权限", e);
        }
    }

    private Workbook buildExcel(DownloadRolePermissionTemplateVo vo) {
        Workbook wb = new XSSFWorkbook();
        this.createPermissionSheet(wb, vo.getRolePermissionExcelVoList());
        this.createDataPermissionSheet(wb, vo.getRoleDataPermissionExcelVoList());
        return wb;
    }

    public void createPermissionSheet(Workbook wb, List<DownloadRolePermissionExcelVo> list){
        List<Field> fieldList = getColumn(null, DownloadRolePermissionExcelVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        Sheet flight = buildHeader(fieldList, wb, ai.getAndIncrement(), "模块权限");
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createDataPermissionSheet(Workbook wb, List<DownloadRoleDataPermissionExcelVo> list){
        List<Field> fieldList = getColumn(null, DownloadRoleDataPermissionExcelVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        Sheet flight = buildHeader(fieldList, wb, ai.getAndIncrement(), "数据权限");
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void downloadExcelEmployee(HttpServletResponse response, EmployeeDownloadTemplate vo) {
        try {
            Workbook workbook = buildExcel(vo);
            String filename = URLEncoder.encode(vo.getFileName() + "." + ExcelPostEnum.xlsx, "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("人员信息", e);
            MetricService.metricOrgOrEmployeeCounter(ORGANIZATION_MANAGE_DOWNLOAD_EMPLOYEE, false, SYNC);
        }
        MetricService.metricOrgOrEmployeeCounter(ORGANIZATION_MANAGE_DOWNLOAD_EMPLOYEE, true, SYNC);
    }

    public void downloadExcelEmployeeWithLock(HttpServletResponse response, EmployeeDownloadTemplate vo) {
        try {
            XSSFWorkbook workbook = buildLockExcel(vo);
            String filename = URLEncoder.encode(vo.getFileName() + "." + ExcelPostEnum.xlsx, "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("人员信息", e);
            MetricService.metricOrgOrEmployeeCounter(ORGANIZATION_MANAGE_DOWNLOAD_EMPLOYEE, false, SYNC);
        }
        MetricService.metricOrgOrEmployeeCounter(ORGANIZATION_MANAGE_DOWNLOAD_EMPLOYEE, true, SYNC);
    }

    public void downloadExcelOrgInfo(HttpServletResponse response, OrgInfoDownloadTemplate vo) {
        try {
            //构建excel
            Workbook workbook = buildExcel(vo);
            String filename = URLEncoder.encode(vo.getFileName() + "." + ExcelPostEnum.xlsx, "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("组织信息", e);
            MetricService.metricOrgOrEmployeeCounter(MetricService.ORGANIZATION_MANAGE_DOWNLOAD_ORG, false, SYNC);
        }
        MetricService.metricOrgOrEmployeeCounter(MetricService.ORGANIZATION_MANAGE_DOWNLOAD_ORG, true, SYNC);
    }

    public void downloadExcelOrgInfoWithLock(HttpServletResponse response, OrgInfoDownloadTemplate vo) {
        try {
            //构建excel
            Workbook workbook = buildExcelWithLock(vo);
            String filename = URLEncoder.encode(vo.getFileName() + "." + ExcelPostEnum.xlsx, "utf-8");
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("组织信息", e);
            MetricService.metricOrgOrEmployeeCounter(MetricService.ORGANIZATION_MANAGE_DOWNLOAD_ORG, false, SYNC);
        }
        MetricService.metricOrgOrEmployeeCounter(MetricService.ORGANIZATION_MANAGE_DOWNLOAD_ORG, true, SYNC);
    }

    private Workbook buildExcel(EmployeeDownloadTemplate vo) {
        Workbook wb = new XSSFWorkbook();
        createEmployeeSheet(wb, vo.getEmployeeDownloadResponseVoList());
        createIdCardSheet(wb, vo.getEmployeeDownloadUserIdCardResponseVoList());
        return wb;
    }

    private XSSFWorkbook buildLockExcel(EmployeeDownloadTemplate vo) throws IOException {
        String fileName = FileTemplateEnum.SyncEmpTemplate.getDealMsg();
        InputStream inputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(String.format("syncorgexceltemplate/%s", fileName));
        XSSFWorkbook wb = new XSSFWorkbook(inputStream);
        createLockEmployeeSheet(wb, vo.getEmployeeInfoExcelColumnVOList());
        createLockIdCardSheet(wb, vo.getEmployeeDownloadUserIdCardResponseVoList());
        return wb;
    }

    private Workbook buildExcel(OrgInfoDownloadTemplate vo) {
        XSSFWorkbook wb = new XSSFWorkbook();
        // 组织
        this.createOrgInfoSheet(wb, vo.getOrgInfoDownloadResponseVoList());
        // 发票
        this.createInvoiceInfoSheet(wb, vo.getOrgInvoiceInfoDownloadResponseVoList());
        // 配送
        this.createDeliveryInfoSheet(wb, vo.getOrgDeliveryInfoDownloadResponseVoList());
        // 职级
        this.createPostInfoSheet(wb, vo.getOrgPostInfoDownloadResponseVoList());

        return wb;
    }

    private Workbook buildExcelWithLock(OrgInfoDownloadTemplate vo) throws IOException {
        String fileName = FileTemplateEnum.SyncOrgTemplate.getDealMsg();
        InputStream inputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(String.format("syncorgexceltemplate/%s", fileName));
        XSSFWorkbook wb = new XSSFWorkbook(inputStream);
        // 组织
        this.createLockOrgInfoSheet(wb, vo.getOrgInfoExcelColumnVOList());
        // 联系人
        this.createLockOrgContanctInfoSheet(wb, vo.getOrgContactExcelColumnVOList());
        // 发票
        this.createLockInvoiceInfoSheet(wb, vo.getOrgInvoiceInfoExcelColumnVOList());
        // 配送
        this.createLockDeliveryInfoSheet(wb, vo.getOrgDeliveryInfoExcelColumnVOList());
        // 组织配置
        this.createLockOrgConfigSheet(wb, vo.getOrgConfigExcelColumnVOList());
        // 支付配置
        this.createLockPayConfigSheet(wb, vo.getPayTypeConfigExcelColumnVOList());

        return wb;
    }

    public void createEmployeeSheet(Workbook wb, List<EmployeeDownloadResponseVo> list){
        List<Field> fieldList = getColumn(null, EmployeeDownloadResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        Sheet flight = buildHeader(fieldList, wb, ai.getAndIncrement(), "人员信息");
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createLockEmployeeSheet(XSSFWorkbook wb, List<EmployeeInfoExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, EmployeeInfoExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        ai.getAndIncrement();
        XSSFSheet flight = wb.getSheetAt(0);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                    if(cell.getColumnIndex() == 0 || cell.getColumnIndex() == 2|| cell.getColumnIndex() == 3){
                        CellStyle lockedStyle = wb.createCellStyle();
                        lockedStyle.setLocked(true); // 设置样式为锁定
                        lockedStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 设置背景色
                        lockedStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                        cell.setCellStyle(lockedStyle); // 设置样式为锁定
                    }else {
                        CellStyle unLockStyle = wb.createCellStyle();
                        unLockStyle.setLocked(false); // 设置样式为锁定
                        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
                        cell.setCellStyle(unLockStyle);
                    }
                });
            });
        }
        flight.protectSheet("123456");
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(false);
        sheetProtection.setInsertRows(false);
        sheetProtection.setInsertHyperlinks(false);
        sheetProtection.setDeleteColumns(false);
        sheetProtection.setDeleteRows(false);

        // 锁定工作表时，开启自动过滤
        setLockProperties(wb, flight.getSheetName(), 1, 1, 0, fieldList.size());
        // 额外解锁从非数据行开始的1000行，100+列
        ExcelUtils.unlockRow(wb, flight.getSheetName(), list.size() + 1, list.size() + 1001);
        // 额外解锁从非数据列开始的100列，数据量行
        ExcelUtils.unlockRowColumnCell(wb, flight.getSheetName(), 0, list.size() + 1, fieldList.size(),
                fieldList.size() + 100);
    }

    private void createIdCardSheet(Workbook wb, List<EmployeeDownloadUserIdCardResponseVo> list) {
        List<Field> fieldList = getColumn(null, EmployeeDownloadUserIdCardResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        Sheet flight = buildHeader(fieldList, wb, ai.getAndIncrement(), "证件");
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    private void createLockIdCardSheet(XSSFWorkbook wb, List<EmployeeDownloadUserIdCardResponseVo> list) {
        List<Field> fieldList = getColumn(null, EmployeeDownloadUserIdCardResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        Sheet flight = wb.getSheetAt(1);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if (value != null) {
                        cell.setCellValue(value.toString());

                        CellStyle unLockStyle = wb.createCellStyle();
                        unLockStyle.setLocked(false); // 设置样式为锁定
                        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
                        cell.setCellStyle(unLockStyle);
                    }
                });
            });
        }
    }

    public void createOrgInfoSheet(XSSFWorkbook wb, List<OrgInfoDownloadResponseVo> list){
        List<Field> fieldList = getColumn(null, OrgInfoDownloadResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        XSSFSheet flight = buildHeaderNew(fieldList, wb, ai.getAndIncrement(), "组织");
        flight.protectSheet("123456");
        //单元格锁定的样式
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        XSSFCellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if ("orgId".equals(field.getName())) {
                        cell.setCellStyle(cellStyle);
                    } else {
                        cell.setCellStyle(unLockStyle);
                    }
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(true);
        sheetProtection.setInsertRows(true);
        sheetProtection.setInsertHyperlinks(true);
        sheetProtection.setDeleteColumns(true);
        sheetProtection.setDeleteRows(true);
    }


    public void createLockOrgInfoSheet(XSSFWorkbook wb, List<OrgInfoExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgInfoExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        ai.getAndIncrement();
        XSSFSheet flight = wb.getSheetAt(0);
        flight.protectSheet("123456");
        //单元格锁定的样式
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        XSSFCellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false); // 设置样式为锁定
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    // 组织编码和上级组织编码不可编辑
                    if(cell.getColumnIndex() == 0 || cell.getColumnIndex() == 3){
                        cell.setCellStyle(cellStyle);
                    } else {
                        cell.setCellStyle(unLockStyle);
                    }
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(true);
        sheetProtection.setInsertRows(true);
        sheetProtection.setInsertHyperlinks(true);
        sheetProtection.setDeleteColumns(true);
        sheetProtection.setDeleteRows(true);

        // 锁定工作表时，开启自动过滤
        setLockProperties(wb, flight.getSheetName(), 1, 1, 0, fieldList.size());
        // 额外解锁从非数据行开始的1000行，100+列
        ExcelUtils.unlockRow(wb, flight.getSheetName(), list.size() + 1, list.size() + 1001);
        // 额外解锁从非数据列开始的100列，数据量行
        ExcelUtils.unlockRowColumnCell(wb, flight.getSheetName(), 0, list.size() + 1, fieldList.size(),
                fieldList.size() + 100);
    }

    public void createInvoiceInfoSheet(XSSFWorkbook wb, List<OrgInvoiceInfoDownloadResponseVo> list){
        List<Field> fieldList = getColumn(null, OrgInvoiceInfoDownloadResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        XSSFSheet flight = buildHeaderNew(fieldList, wb, ai.getAndIncrement(), "发票");
        flight.protectSheet("123456");
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if ("orgId".equals(field.getName())) {
                        cell.setCellStyle(cellStyle);
                    } else {
                        cell.setCellStyle(unLockStyle);
                    }
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(true);
        sheetProtection.setInsertRows(true);
        sheetProtection.setInsertHyperlinks(true);
        sheetProtection.setDeleteColumns(true);
        sheetProtection.setDeleteRows(true);
    }

    public void createLockOrgContanctInfoSheet(XSSFWorkbook wb, List<OrgContactExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgContactExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight = wb.getSheetAt(1);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createLockInvoiceInfoSheet(XSSFWorkbook wb, List<OrgInvoiceInfoExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgInvoiceInfoExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight = wb.getSheetAt(2);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createDeliveryInfoSheet(XSSFWorkbook wb, List<OrgDeliveryInfoDownloadResponseVo> list){
        List<Field> fieldList = getColumn(null, OrgDeliveryInfoDownloadResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        XSSFSheet flight = buildHeaderNew(fieldList, wb, ai.getAndIncrement(), "配送");
        flight.protectSheet("123456");
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if ("orgId".equals(field.getName())) {
                        cell.setCellStyle(cellStyle);
                    } else {
                        cell.setCellStyle(unLockStyle);
                    }
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(true);
        sheetProtection.setInsertRows(true);
        sheetProtection.setInsertHyperlinks(true);
        sheetProtection.setDeleteColumns(true);
        sheetProtection.setDeleteRows(true);
    }

    public void createLockDeliveryInfoSheet(XSSFWorkbook wb, List<OrgDeliveryInfoExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgDeliveryInfoExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight =  wb.getSheetAt(3);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createPostInfoSheet(XSSFWorkbook wb, List<OrgPostInfoDownloadResponseVo> list){
        List<Field> fieldList = getColumn(null, OrgPostInfoDownloadResponseVo.class, false);
        AtomicInteger ai = new AtomicInteger();
        XSSFSheet flight = buildHeaderNew(fieldList, wb, ai.getAndIncrement(), "职级");
        flight.protectSheet("123456");
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    if ("orgId".equals(field.getName())) {
                        cell.setCellStyle(cellStyle);
                    } else {
                        cell.setCellStyle(unLockStyle);
                    }
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
        flight.enableLocking();
        CTSheetProtection sheetProtection = flight.getCTWorksheet().getSheetProtection();
        sheetProtection.setSelectLockedCells(false);
        sheetProtection.setSelectUnlockedCells(false);
        sheetProtection.setFormatCells(false);
        sheetProtection.setFormatColumns(false);
        sheetProtection.setFormatRows(false);
        sheetProtection.setInsertColumns(true);
        sheetProtection.setInsertRows(true);
        sheetProtection.setInsertHyperlinks(true);
        sheetProtection.setDeleteColumns(true);
        sheetProtection.setDeleteRows(true);
    }

    public void createLockPostInfoSheet(XSSFWorkbook wb, List<OrgPostInfoExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgPostInfoExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight =  wb.getSheetAt(4);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createLockOrgConfigSheet(XSSFWorkbook wb, List<OrgConfigExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, OrgConfigExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight =  wb.getSheetAt(4);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    public void createLockPayConfigSheet(XSSFWorkbook wb, List<PayTypeConfigExcelColumnVO> list){
        List<Field> fieldList = getColumn(null, PayTypeConfigExcelColumnVO.class, false);
        AtomicInteger ai = new AtomicInteger();
        ai.getAndIncrement();
        XSSFSheet flight =  wb.getSheetAt(5);
        CellStyle cellStyle = wb.createCellStyle();
        //单元格锁定的样式
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setLocked(true);
        //单元格不锁定的样式
        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);
        unLockStyle.setDataFormat(wb.createDataFormat().getFormat("@"));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(t -> {
                Row row1 = flight.createRow(ai.getAndIncrement());
                AtomicInteger aj = new AtomicInteger();
                fieldList.forEach(field -> {
                    Object value = "";
                    try {
                        value = field.get(t);
                    } catch (IllegalAccessException e) {
                        log.error(e.getMessage());
                    }
                    Cell cell = row1.createCell(aj.getAndIncrement());
                    cell.setCellStyle(unLockStyle);
                    if (value != null) {
                        cell.setCellValue(value.toString());
                    }
                });
            });
        }
    }

    private XSSFSheet buildHeaderNew(List<Field> fieldList, XSSFWorkbook wb, int index, String sheetName) {
        AtomicInteger aj = new AtomicInteger();
        CellStyle lockStyle = wb.createCellStyle();
        lockStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        lockStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        lockStyle.setLocked(true);

        CellStyle unLockStyle = wb.createCellStyle();
        unLockStyle.setLocked(false);

        XSSFSheet sheet = wb.createSheet(sheetName);
        Row row = sheet.createRow(index);
        for (int i = 0; i < fieldList.size(); i++) {
            ExcelColumn annotation = fieldList.get(i).getAnnotation(ExcelColumn.class);
            String columnName = "";
            if (annotation != null) {
                columnName = annotation.value();
            }
            Cell cell = row.createCell(aj.getAndIncrement());
            CellStyle cellStyle = wb.createCellStyle();
            Font font = wb.createFont();
            font.setBold(Boolean.TRUE);
            if (annotation != null) {
                if (Objects.equals(annotation.headerColor(), "red")) {
                    font.setColor(IndexedColors.RED.getIndex());
                }
            }
            cellStyle.setFont(font);
            if ("orgId".equals(fieldList.get(i).getName())) {
                lockStyle.setFont(font);
                cell.setCellStyle(lockStyle);
            } else {
                cellStyle.setFont(font);
                cell.setCellStyle(cellStyle);
                sheet.setDefaultColumnStyle(i, unLockStyle);
            }
            cell.setCellValue(columnName);
        }
        return sheet;
    }


    private Sheet buildHeader(List<Field> fieldList, Workbook wb, int index, String sheetName) {
        Sheet sheet = wb.createSheet(sheetName);
        Row row = sheet.createRow(index);
        AtomicInteger aj = new AtomicInteger();
        //写入头部
        fieldList.forEach(field -> {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            String columnName = "";
            if (annotation != null) {
                columnName = annotation.value();
            }

            Cell cell = row.createCell(aj.getAndIncrement());
            CellStyle cellStyle = wb.createCellStyle();
            Font font = wb.createFont();
            font.setBold(Boolean.TRUE);
            if (annotation != null) {
                if (Objects.equals(annotation.headerColor(), "red")) {
                    font.setColor(IndexedColors.RED.getIndex());
                }
            }
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            cell.setCellValue(columnName);
        });
        return sheet;
    }

    /**
     * excel锁定时，允许开启自动筛选
     *
     * @param workbook 工作表
     * @param firstRow 起始行
     * @param lastRow 结束行，筛选的范围
     * @param firstCol 起始列
     * @param lastCol 结束列，删选的字段
     */
    private void setLockProperties(XSSFWorkbook workbook, String sheetName, int firstRow, int lastRow, int firstCol,
        int lastCol) {

        XSSFSheet sheet = workbook.getSheet(sheetName);
        // 设置筛选范围
        CellRangeAddress filterRange = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol - 1);
        sheet.setAutoFilter(filterRange);
        // 允许筛选
        sheet.lockAutoFilter(false);
        // 允许排序
        sheet.lockSort(false);
        // 允许排序
        sheet.lockSort(false);
        // 允许设置单元格格式
        sheet.lockFormatCells(false);
        // 允许调整列宽
        sheet.lockFormatColumns(false);
        // 允许调整行高
        sheet.lockFormatRows(false);
        // 允许数据透视表
        sheet.lockPivotTables(false);
    }

    /**
     * 解锁超出的行列的单元格
     *
     * @param startRow
     * @param endRow
     * @param startColumn
     * @param endColumn
     */
    public static void unlockRowColumnCell(Workbook wb, String sheetName, int startRow, int endRow, int startColumn,
                                           int endColumn) {
        // 设置解锁表格列样式
        CellStyle unLockColStyle = wb.createCellStyle();
        unLockColStyle.setLocked(false);

        Sheet sheet = wb.getSheet(sheetName);

        // 超出部分需要新建cell
        for (int i = startRow; i < endRow; i++) {
            Row row = sheet.getRow(i);
            if (row == null) {
                row = sheet.createRow(i);
            }
            for (int j = startColumn; j < endColumn; j++) {
                // 搜索不需要的列数
                Cell cell = row.getCell(j);
                if (cell == null) {
                    cell = row.createCell(j);
                }
                cell.setCellStyle(unLockColStyle);
            }
        }
    }

    public static void unlockRow(Workbook wb, String sheetName, int startRow, int endRow) {
        // 设置解锁表格列样式
        CellStyle unLockColStyle = wb.createCellStyle();
        unLockColStyle.setLocked(false);

        Sheet sheet = wb.getSheet(sheetName);

        // 超出部分需要新建cell
        for (int i = startRow; i < endRow; i++) {
            Row row = sheet.getRow(i);
            if (row == null) {
                row = sheet.createRow(i);
            }
            row.setRowStyle(unLockColStyle);
        }
    }
}